
package com.coldchain.gate.ratelimit.config.properties;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;


@Validated
@ConfigurationProperties(RateLimitProperties.PREFIX)
public class RateLimitProperties {

    public static final String PREFIX = "zuul.ratelimit";

    private Policy defaultPolicy;
    @NotNull
    private Map<String, Policy> policies = Maps.newHashMap();
    private boolean behindProxy;
    private boolean enabled;
    @NotNull
    @Value("${spring.application.name:rate-limit-application}")
    private String keyPrefix;
    @NotNull
    private Repository repository = Repository.IN_MEMORY;

    public enum Repository {
        REDIS, CONSUL, JPA, IN_MEMORY
    }

    public Optional<Policy> getPolicy(String key) {
        return Optional.ofNullable(policies.getOrDefault(key, defaultPolicy));
    }

    public Policy getDefaultPolicy() {
        return defaultPolicy;
    }

    public void setDefaultPolicy(Policy defaultPolicy) {
        this.defaultPolicy = defaultPolicy;
    }

    @NotNull
    public Map<String, Policy> getPolicies() {
        return policies;
    }

    public void setPolicies(@NotNull Map<String, Policy> policies) {
        this.policies = policies;
    }

    public boolean isBehindProxy() {
        return behindProxy;
    }

    public void setBehindProxy(boolean behindProxy) {
        this.behindProxy = behindProxy;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    @NotNull
    public String getKeyPrefix() {
        return keyPrefix;
    }

    public void setKeyPrefix(@NotNull String keyPrefix) {
        this.keyPrefix = keyPrefix;
    }

    @NotNull
    public Repository getRepository() {
        return repository;
    }

    public void setRepository(@NotNull Repository repository) {
        this.repository = repository;
    }

    public static class Policy {

        @NotNull
        private Long refreshInterval = TimeUnit.MINUTES.toSeconds(1L);
        @NotNull
        private Long limit;
        @NotNull
        private List<Type> type = Lists.newArrayList();

        public enum Type {
            ORIGIN, USER, URL
        }

        @NotNull
        public Long getRefreshInterval() {
            return refreshInterval;
        }

        public void setRefreshInterval(@NotNull Long refreshInterval) {
            this.refreshInterval = refreshInterval;
        }

        @NotNull
        public Long getLimit() {
            return limit;
        }

        public void setLimit(@NotNull Long limit) {
            this.limit = limit;
        }

        @NotNull
        public List<Type> getType() {
            return type;
        }

        public void setType(@NotNull List<Type> type) {
            this.type = type;
        }
    }
}
